<?php

namespace App\Morefun\Prize;

use Illuminate\Container\Container;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Arr;

class ExchangeRecordSynchronizer
{
    const EXCHANGE_RECORD_KEY = 'exchange:records';
    const RECORD_TABLE = 'activity_records';
    /**
     * @var \Redis
     */
    protected $redis;
    protected $database;

    public function sync()
    {
        $again = [];

        while (($cipher = $this->redis()->lPop(self::EXCHANGE_RECORD_KEY)) !== null) {
            if (null === $cipher) {
                continue;
            }

            $record = json_decode($cipher, true);

            if (Arr::get($record, 'times', 0) >= 10) {
                continue;
            }

            $which = [['id', '=', Arr::get($record, 'id')]];

            if (!$this->hasDrawRecord($which)) {
                $record['times']++;
                $again[] = json_encode($record);
                continue;
            }

            $this->mergeToDatabase($which, $record);
        }

        if ($again) {
            $this->reEnterToRedis($again);
        }
    }

    protected function hasDrawRecord(array $which)
    {
        return $this->database()->table(self::RECORD_TABLE)->where($which)->exists();
    }

    protected function mergeToDatabase(array $which, array $record)
    {
        $coupon = Arr::get($record, 'coupon', '');
        return $this->database()->table(self::RECORD_TABLE)
            ->where($which)
            ->update([
                'name' => Arr::get($record, 'name'),
                'mobile' => Arr::get($record, 'mobile'),
                'address' => Arr::get($record, 'address', ''),
                'coupon' => $coupon,
                'is_confirm' => 1,
            ]);
    }

    protected function reEnterToRedis(array $records)
    {
        $this->redis()->pipeline(function ($redis) use ($records) {
            foreach ($records as $record) {
                $redis->lpush(self::EXCHANGE_RECORD_KEY, $record);
            }
        });
    }

    protected function redis()
    {
        if (!$this->redis) {
            $this->redis = Container::getInstance()->make('redis');
        }

        return $this->redis;
    }

    /**
     * @return Builder
     */
    protected function database()
    {
        if (!$this->database){
            $this->database = Container::getInstance()->make('db');
        }

        return $this->database;
    }
}
